/**
 * @file swei_package.c
 * @brief
 * @author  ()
 * @version 1.0
 * @date 2024-09-13
 *
 * @copyright Copyright (C) 2019 Queclink Wireless Solutions (ShenZhen) Co., Ltd. All Rights Reserved.
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version <th>Author  <th>Description
 * <tr><td>2024-09-13 <td>1.0     <td>     <td>内容
 * </table>
 */
#include "include/port/swei_log.h"

#include "include/port/swei_fw_info.h"
#include "include/port/swei_wrapper.h"
#include "include/port/swei_version.h"
#include "include/swei_package.h"
#include "include/swei_status.h"
#include "include/swei_config.h"
#include "include/swei_crc16.h"
#include "public/errno.h"


#include "global.h"
#include "modem/qlmodem/include/qlmodemconfdefs.h"
#include "drivers/gnss/skeleton/gnss_info_process.h"

#pragma pack(1)
/* gps消息结构体对从sdk中获取到的数据进行过滤,仅保留我们需要的, 美格当前sdk中不提供东西经南北纬标志,通过经纬度正负号区分 */
typedef struct
{
    char gps_num;                /* gps 个数 */
    int32_t utc_time;            /* GPS定位点时间 */
    int32_t latitude;            /* 纬度 北纬为正数，南纬为负数，十进制放大10000000得出结果。*/
    int32_t longitude;           /* 经度 东经为正数，西经为负数，十进制放大10000000得出结果。*/
    unsigned char satellite_num; /* 卫星数量 */
    unsigned short speed;        /* 对地速度 */
    unsigned short altitude;     /* 高度 */
    short status;                /* 航向/状态 */
    unsigned char upload_mode;   /* 上报模式*/
    char cn[3];                  /* 前3个卫星的信号强度*/
} gps_info_st;
#pragma pack()

// 基站信息
#pragma pack(1)
// 基站信息 头
typedef struct
{
    int timestamp;
    unsigned char lbs_type;
    short mcc;
    short mnc;
    unsigned char lbs_num;
} stations_info_head_st;

typedef struct
{
    short lac;              // 区码
    int cellid;             // 0~65535
    unsigned char csq_rssi; // 信号强度
} stations_info_st;         // 2g和3g

typedef struct
{
    int lac; // 区码
    long long int cellid;
    unsigned char csq_rssi; // 信号强度
} stations_info_st_4_5;     // 4g和5g
#pragma pack()

typedef enum
{
	LOT_MOD_MIN,
	LOT_GSM_MODE,    /*2G*/
	LOT_WCDMA_MODE,  /*3G*/
	LOT_LTE_MODE,    /*4G*/
	LOT_MODE_MAX
}fw_cell_lot_e_type;

typedef enum
{
    AUDIO1,
    AUDIO2,
    SELF_DEFINE,
}audio_type;

static int32_t swei_package_body_data(uint16_t protocol_id, uint8_t *p_out_body, uint16_t *out_body_len, common_msg_st *p_common_msg, uint8_t *p_in_data);
static int32_t swei_package_login_msg_body_data_new(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_all_protocol_data(void *p_out_protocol_data, int32_t body_len);
static int32_t swei_package_dev_ack_body_data(uint8_t *p_in_data, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_activate_body_data(common_msg_st *p_in_data, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_gps_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_lbs_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_wifi_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_warning_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_can_body_data(common_msg_st *p_msg, uint8_t *p_in_data, uint8_t *body_data, uint16_t *body_data_len);
static int32_t swei_package_config_info_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len);
/***********************************************************************
 * 函数名称: swei_pack_msg_seq
 * 作    者:  yanfeng
 * 设计日期: 2023-08-21 16:55
 * 功能描述: 获取消息序列号
 * 参    数: 多个参数时，参数会有多行
 * 返 回 值:
 * 修改日期:          修改人          修改内容
 ***********************************************************************/
uint16_t swei_pack_msg_seq(void)
{
    static uint16_t sequence_number = 0;

    // pthread_mutex_lock(&seq_mutex_lock);
    sequence_number++;
    if (sequence_number >= MAX_SEQUENCE_NUMBER)
    {
        sequence_number = 0;
    }
    // pthread_mutex_unlock(&seq_mutex_lock);

    return sequence_number;
}

/***********************************************************************
 * 函数名称: swei_package_protocol_msg
 * 作    者:  yanfeng
 * 设计日期: 2023-08-21 16:55
 * 功能描述: 输入通用队列消息,封装成和云平台交互的协议格式数据
 * 参    数:   p_common_msg: 从通用队列中获取到的队列通用消息
             p_in_data: 注意:如果不想使用消息队列来传递消息,这里p_common_msg可以传空,调用这可以将待封装的消息通过p_in_data传入
             protocol_id:待封装的协议ID,调用自行根据业务需要传入该id
             p_out_data: 封装的协议数据
 * 返 回 值: 封装完的整个协议消息的长度

 * 修改日期:          修改人          修改内容
 ***********************************************************************/
int32_t swei_package_protocol_msg(common_msg_st *p_common_msg, uint8_t *p_in_data, uint16_t protocol_id, uint8_t *p_out_protocol_data)
{
    uint8_t *p_body_data;
    uint16_t body_len = 0;
    uint16_t total_data_len = 0;

    if (p_out_protocol_data == NULL)
    {
        log_e("tbox p_out_data null ptr");
        return -EPERM;
    }

    if (p_common_msg == NULL && p_in_data == NULL)
    {
        log_e("tbox p_in_data null ptr");
        return -EPERM;
    }

    /* 第1步：先处理body体,偏移到消息包内容的位置 */
    p_body_data = p_out_protocol_data + sizeof(NET_PROTOCOL_HEAD_ST);

    /* 第2步：根据protocol_id打包消息体,重要:这部分需要各模块根据自己的需要进行body打包 */
    if (0 != swei_package_body_data(protocol_id, p_body_data, &body_len, p_common_msg, p_in_data))
    {
        log_e("tbox package body data fail [id %d]!", protocol_id);
        return -EAGAIN;
    }

    /* 第3步: 封装整个完整格式的协议消息 */
    total_data_len = swei_package_all_protocol_data(p_out_protocol_data, body_len);

    return total_data_len;
}

/**
 * @description: 获取每条包信息内容，自行转换，实现函数写在该c文件内
 * @param {short} prorocol_id
 * @param {unsigned char} *body_data = id + content
 * @param {int32_t} *body_data_len
 * @param {common_msg_st} msg 队列内容
 * @param uint8_t *p_in_data ：如果不使用消息队列的消息的话,可以将待封装的消息通过p_in_data传入
 * @return {*}
 * @Date: 2023-09-07 15:58:49
 * @modification:
 */
static int32_t swei_package_body_data(uint16_t protocol_id, uint8_t *p_out_body, uint16_t *out_body_len, common_msg_st *p_common_msg, uint8_t *p_in_data)
{
    int32_t ret_len = 0;

    if (NULL == p_out_body || NULL == out_body_len) {
        log_e("Null pointer");
        return 0;
    }

    // KLV 之 K
    p_out_body[0] = (protocol_id >> 8) & 0xff;
    p_out_body[1] = protocol_id & 0xff;

    // 按照protocol_id打包KLV
    switch (protocol_id) {
        case NET_PROTOCOL_ID_LOGSTEP_NEW:
            ret_len = swei_package_login_msg_body_data_new(p_common_msg, p_out_body + 2, out_body_len);
            // elog_hexdump("login_msg_body_data_new", 16, p_out_body + 2, *out_body_len);
            break;

        case NET_PROTOCOL_ID_HEART_BEAT: // 不需要处理，没有内容
            ret_len = 0;
            break;

        case NET_PROTOCOL_ID_GPS:
            ret_len = swei_package_gps_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_LBS:
            ret_len = swei_package_lbs_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_WIFI:
            ret_len = swei_package_wifi_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_WARNING:
            ret_len = swei_package_warning_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_DEVICE_STATUS:
            ret_len = swei_package_can_body_data(p_common_msg, p_in_data, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_DEVICE_ACK:
        case NET_PROTOCOL_ID_DEVICE_CMD_ACK:
            ret_len = swei_package_dev_ack_body_data(p_in_data, p_out_body + 2, out_body_len);
            elog_hexdump("dev_ack_body_data", 16, p_out_body + 2, *out_body_len);
            break;

        case NET_PROTOCOL_ID_REQUEST_ACTIVATE: // 设备请求激活信息，目前没有数据，注释下面函数
            ret_len = swei_package_activate_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        case NET_PROTOCOL_ID_UPLOAD_CONFIG_INFO:
            ret_len = swei_package_config_info_body_data(p_common_msg, p_out_body + 2, out_body_len);
            break;

        default:
            break;
    }

    *out_body_len = *out_body_len + 2; // 加 protocol_id 的长度

    return ret_len;
}

#include "misc/version.h"
/**
 * @description: 封装新协议登录包
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2023-08-10 16:53:42
 * @modification:
 */
static int32_t swei_package_login_msg_body_data_new(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    uint8_t get_imei[8];
    uint16_t body_len = 0;
    char str[21] = "";
    char sn[DEVICE_SN_LEN] = "";

    /* 1.写入IMEI */
    swei_get_device_info(IMEI_INFO_BCD, get_imei, sizeof(get_imei));
    memcpy(body_data, get_imei, IMEI_BCD_LEN);
    body_len += IMEI_BCD_LEN;

    /* 2.写入类型识别码,目前固定为0x01 */
    body_data[body_len] = 0x00;
    body_len += 1;
    body_data[body_len] = 0x01;
    body_len += 1;

    /* 3.写入协议版本号 */
    body_data[body_len] = NET_PROTOCOL_VERSION;
    body_len += 1;

    /* 4.写入设备SN, L-V格式 */
    swei_get_device_info(SN_INFO, (unsigned char *)sn, sizeof(sn));
    memset(str, 0, sizeof(str));
    memcpy(str, sn, sizeof(str));
    body_data[body_len++] = strlen(str);
    memcpy(body_data + body_len, str, strlen(str));
    body_len += strlen(str);

    /*5.用户名，当前无用户名，以SN上传*/
    body_data[body_len++] = strlen(str);
    memcpy(body_data + body_len, str, strlen(str));
    body_len += strlen(str);

    /* 6.写入密码,L-V格式,目前密码是定死的 */
    body_data[body_len++] = strlen("Sv064#$%");
    memcpy(body_data + body_len, "Sv064#$%", strlen("Sv064#$%"));
    body_len += strlen("Sv064#$%");

    /* 7.写入tbox应用版本号*/
    body_data[body_len++] = strlen(SWEI_SOFTWARE_VERSION);
    memcpy(body_data + body_len, SWEI_SOFTWARE_VERSION, strlen(SWEI_SOFTWARE_VERSION));
    body_len += strlen(SWEI_SOFTWARE_VERSION);

    /* 8.写入sdk lib版本号*/
    #if 0
    char *modem = mmgr_version_get();
    body_data[body_len++] = strlen(modem); // get_fw_lib_version.ver
    memcpy(body_data + body_len, modem, strlen(modem));
    body_len += strlen(modem);
    #else // 依客户要求上传00,建议上传modem版本号
    body_data[body_len++] = strlen("00");
    memcpy(body_data + body_len, "00", strlen("00"));
    body_len += strlen("00");
    #endif

    /* 9.写入sdk版本号 */
    #if 0
    body_data[body_len++] = strlen(qlmodem_version);
    memcpy(body_data + body_len, qlmodem_version, strlen(qlmodem_version));
    body_len += strlen(qlmodem_version);
    #else // 依客户要求上传00,建议上传modem版本号
    body_data[body_len++] = strlen("00");
    memcpy(body_data + body_len, "00", strlen("00"));
    body_len += strlen("00");
    #endif

    /* 10.写入蓝牙版本号 */
    body_data[body_len++] = strlen("00");
    memcpy(body_data + body_len, "00", strlen("00"));
    body_len += strlen("00");

    /* 设置body体长度 */
    *body_data_len = body_len;
    return 0;
}

#include "utils/utils.h"
/**
 * @description: 获取gps定位数据
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2023-08-10 16:53:42
 * @modification:
 */
static int32_t swei_package_gps_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    gps_info_st gps_info; // gps信息，写入队列的数据
    int32_t data_len = 0;

    memcpy(&gps_info, p_msg->msg_content, sizeof(gps_info));

    body_data[data_len++] = gps_info.gps_num;
    data_len += bigending2buf(body_data + data_len, gps_info.utc_time); // 时间戳
    data_len += bigending2buf(body_data + data_len, gps_info.latitude);
    data_len += bigending2buf(body_data + data_len, gps_info.longitude);
    body_data[data_len++] = gps_info.satellite_num;
    body_data[data_len++] = (gps_info.speed >> 8) & 0xff;
    body_data[data_len++] = gps_info.speed & 0xff;
    body_data[data_len++] = (gps_info.altitude >> 8) & 0xff;
    body_data[data_len++] = gps_info.altitude & 0xff;
    body_data[data_len++] = (gps_info.status >> 8) & 0xff;
    body_data[data_len++] = gps_info.status & 0xff;
    body_data[data_len++] = gps_info.upload_mode;
    body_data[data_len++] = gps_info.cn[0];
    body_data[data_len++] = gps_info.cn[1];
    body_data[data_len++] = gps_info.cn[2];

    *body_data_len = data_len;
    return 0;
}




/**
 * @description: 获取基站定位数据
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int} *body_data_len
 * @return {*}
 * @Date: 2023-08-10 16:53:42
 * @modification:
 */
static int32_t swei_package_lbs_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    stations_info_head_st stations_info_head;
    stations_info_st stations_info;         // 基站定位数据
    stations_info_st_4_5 stations_info_4_5; // 基站定位数据
    int32_t data_len = 0;

    memcpy(&stations_info_head, p_msg->msg_content, sizeof(stations_info_head));
    data_len += bigending2buf(body_data + data_len, stations_info_head.timestamp); // 时间戳
    body_data[data_len++] = stations_info_head.lbs_type;                                             // 基站类型
    body_data[data_len++] = (stations_info_head.mcc >> 8) & 0xff;
    body_data[data_len++] = stations_info_head.mcc & 0xff;
    body_data[data_len++] = (stations_info_head.mnc >> 8) & 0xff;
    body_data[data_len++] = stations_info_head.mnc & 0xff;
    body_data[data_len++] = stations_info_head.lbs_num; // lbs数量 msg->msg_content[9]

    int32_t i = 0;
    int32_t lbs_num = stations_info_head.lbs_num; // lbs数量
    for (i = 0; i < lbs_num; i++)
    {
        if (stations_info_head.lbs_type < LOT_LTE_MODE)
        {
            memset(&stations_info, 0, sizeof(stations_info));
            memcpy(&stations_info, p_msg->msg_content + data_len, sizeof(stations_info));

            body_data[data_len++] = (stations_info.lac >> 8) & 0xff;
            body_data[data_len++] = stations_info.lac & 0xff;
            data_len += bigending2buf(body_data + data_len, stations_info.cellid);
            body_data[data_len++] = stations_info.csq_rssi;
        }
        else
        {
            memset(&stations_info_4_5, 0, sizeof(stations_info_4_5));
            memcpy(&stations_info_4_5, p_msg->msg_content + data_len, sizeof(stations_info_4_5));
            data_len += bigending2buf(body_data + data_len, stations_info_4_5.lac);
            body_data[data_len++] = (stations_info_4_5.cellid >> 56) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 48) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 40) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 32) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 24) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 16) & 0xff;
            body_data[data_len++] = (stations_info_4_5.cellid >> 8) & 0xff;
            body_data[data_len++] = stations_info_4_5.cellid & 0xff;
            body_data[data_len++] = stations_info_4_5.csq_rssi;
        }
    }
    *body_data_len = data_len;

    return 0;
}


/**
 * @description: 获取wifi定位数据
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int} *body_data_len
 * @return {*}
 * @Date: 2023-08-10 16:53:42
 * @modification:
 */
static int32_t swei_package_wifi_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    int32_t timestamp = 0;
    uint8_t wifi_num = 0;
    int32_t data_len = 0;

    memcpy(&timestamp, p_msg->msg_content, sizeof(int32_t));
    data_len += bigending2buf(body_data + data_len, timestamp); // 时间戳
    wifi_num = p_msg->msg_content[data_len];
    body_data[data_len++] = wifi_num;

    memcpy(body_data + data_len, p_msg->msg_content + data_len, p_msg->msg_len - data_len);

    *body_data_len = p_msg->msg_len;
    return 0;
}

/**
 * @description:
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2023-09-28 09:00:00
 * @modification:
 */
static int32_t swei_package_warning_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    int32_t data_len = 0;
    uint32_t timestamp;

    /* 取时间戳 */
    timestamp = swei_get_device_timestamp();

    /* 两字节告警ID,发送时要按大端序高字节先发 */
    body_data[data_len++] = p_msg->msg_content[0];
    body_data[data_len++] = p_msg->msg_content[1];

    /* 时间戳 */
    body_data[data_len++] = (timestamp >> 24) & 0xff;
    body_data[data_len++] = (timestamp >> 16) & 0xff;
    body_data[data_len++] = (timestamp >> 8) & 0xff;
    body_data[data_len++] = timestamp & 0xff;

    /* 告警内容长度 */
    body_data[data_len++] = p_msg->msg_content[2];

    /* 告警内容大于0的话,还需要将告警内容拷贝到send_buf中*/
    if (p_msg->msg_content[2] > 0)
    {
        /* to-do: */
    }

    *body_data_len = data_len;
    return 0;
}

/**
 * @description:
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2023-08-10 16:53:42
 * @modification:
 */
static int32_t swei_package_can_body_data(common_msg_st *p_msg, uint8_t *p_in_data, uint8_t *body_data, uint16_t *body_data_len)
{
    if ((NULL == p_msg) && (NULL == p_in_data))
    {
        log_e("tbox error can p_msg and p_in_data");
        return -1;
    }
    if (NULL == p_in_data)
    {
        *body_data_len = p_msg->msg_len;
        memcpy(body_data, p_msg->msg_content, *body_data_len); // memcpy之前各上传数据包各自处理完大小端问题；

        log_i("tbox state id is 0x%x,data len is 0x%x,data is ", ((p_msg->msg_content[0] << 8) | (p_msg->msg_content[1])), p_msg->msg_len);
    }
    else
    {
    }
    return 0;
}

/**
 * @description: 按照协议打包
 * @param {int32_t} prorocol_id 协议标识符
 * @param {void} *data 整条协议，缺头尾数据
 * @param {int32_t} body_data_len
 * @return {data_len/-1}
 * @Date: 2023-09-07 15:45:27
 * @modification:
 */
static int32_t swei_package_all_protocol_data(void *p_out_protocol_data, int32_t body_len)
{
    NET_PROTOCOL_HEAD_ST head;
    NET_PROTOCOL_TAIL_ST tail;
    uint8_t *send_buf = (uint8_t *)p_out_protocol_data;
    int32_t send_buf_idx = 0;

    memset(&head, 0, sizeof(head));
    memset(&tail, 0, sizeof(tail));

    /* 消息起始位为0x7a0x7a*/
    head.head = NET_PROTOCOL_HEAD_NUM;

    /* 给消息长度字段赋值, 消息长度 = 4字节工作ID + 4字节时间戳 + 信息序列号 + 信息内容 + 错误校验*/
    head.len = 4 + 4 + 2 + body_len + 2;
    head.serial_num = swei_pack_msg_seq();

    /* 计算working id*/
    head.working_id = swei_get_workid();

    /* 计算时间戳 */
    head.timestamp = swei_get_device_timestamp();

    /* 开始封装消息的头部和尾部 */
    send_buf_idx = 0;

    /* 封装消息起始位*/
    send_buf[send_buf_idx++] = (head.head >> 8) & 0xff;
    send_buf[send_buf_idx++] = head.head & 0xff;

    /* 封装包长度字段 */
    send_buf[send_buf_idx++] = (head.len >> 8) & 0xff;
    send_buf[send_buf_idx++] = head.len & 0xff;

    /* 封装工作ID字段*/
    send_buf[send_buf_idx++] = (head.working_id >> 24) & 0xff;
    send_buf[send_buf_idx++] = (head.working_id >> 16) & 0xff;
    send_buf[send_buf_idx++] = (head.working_id >> 8) & 0xff;
    send_buf[send_buf_idx++] = (head.working_id) & 0xff;

    /* 封装时间戳字段 */
    send_buf[send_buf_idx++] = (head.timestamp >> 24) & 0xff;
    send_buf[send_buf_idx++] = (head.timestamp >> 16) & 0xff;
    send_buf[send_buf_idx++] = (head.timestamp >> 8) & 0xff;
    send_buf[send_buf_idx++] = (head.timestamp) & 0xff;

    /* 封装消息序列号*/
    send_buf[send_buf_idx++] = (head.serial_num >> 8) & 0xff;
    send_buf[send_buf_idx++] = head.serial_num & 0xff;

    /* 计算消息crc16 包长度到包信息内容的CRC-16值 */
    tail.crc = swei_calc_crc(send_buf + 2, 2 + 4 + 4 + 2 + body_len);
    tail.tail = NET_PROTOCOL_TAIL_NUM;

    send_buf_idx = sizeof(head) + body_len;
    send_buf[send_buf_idx++] = (tail.crc >> 8) & 0xff;
    send_buf[send_buf_idx++] = tail.crc & 0xff;
    send_buf[send_buf_idx++] = (tail.tail >> 8) & 0xff;
    send_buf[send_buf_idx++] = tail.tail & 0xff;

    return send_buf_idx;
}

/**
 * @description: 获取设备通用应答数据
 * @param {uint8_t} *p_in_data
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2023-10-23
 * @modification:
 */
static int32_t swei_package_dev_ack_body_data(uint8_t *p_in_data, uint8_t *body_data, uint16_t *body_data_len)
{
    typedef struct
    {
        uint8_t ack_msg[16];
        uint8_t ack_len;
    } MSG_INFO;
    MSG_INFO msg_info;

    memcpy((void *)&msg_info, (void *)p_in_data, sizeof(MSG_INFO));
    memcpy(body_data, msg_info.ack_msg, msg_info.ack_len);

    *body_data_len = msg_info.ack_len;
    return 0;
}


/**
 * @description:  设备请求激活信息
 * @param {uint8_t} *p_in_data
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2024-11-08
 * @modification:
 */
static int32_t swei_package_activate_body_data(common_msg_st *p_in_data, uint8_t *body_data, uint16_t *body_data_len)
{
    /* 仅ID无数据 */
    if(body_data_len != NULL) {
        *body_data_len = 0;
    }
    return 0;
}




#include "gnss_power_mgr.h"
// 定位模式
typedef enum
{
    LOCATION_MODE_GPS = 0,
    LOCATION_MODE_WIFI,
    LOCATION_MODE_STATIONS
} LOCATION_MODE;

#include "include/swei_alarm.h"
#include "include/swei_location.h"

/**
 * @brief 封装定位信息包
 * @param  data             My Param doc
 * @param  data_len         My Param doc
 * @return int32_t
 */
int32_t swei_packet_loc_data(uint8_t *data, uint16_t data_len)
{
    common_msg_st msg = {0};
    uint16_t protocol_id = 0;
    // int32_t ret = 0;

    // 1. 从loc队列中读取
    if(0 != swei_location_pop(&msg))
    {
        // log_e("location data queue is empty!\r\n")
        return 0;
    }

    /* 根据队列中消息type封装协议ID */
    if (msg.msg_type == LOCATION_MODE_GPS)
    {
        // ret = swei_location_scan_gps_info(&msg);
        protocol_id = NET_PROTOCOL_ID_GPS;
    }
    else if (msg.msg_type == LOCATION_MODE_WIFI)
    {
        // ret = swei_location_scan_wifi_info(&msg);
        protocol_id = NET_PROTOCOL_ID_WIFI;
    }
    else if (msg.msg_type == LOCATION_MODE_STATIONS)
    {
        // ret = swei_location_scan_lbs_info(&msg);
        protocol_id = NET_PROTOCOL_ID_LBS;
    }
    else
    {
        log_e("location data msgtype error, %d!\r\n", msg.msg_type);
        return 0;
    }

    // if(ret < 0)
    // {
    //     log_e("location data packet failed!\r\n");
    //     return 0;
    // }

    /* 封装协议消息 */
    return swei_package_protocol_msg(&msg, NULL, protocol_id, data);
}

/**
 * @brief 封装告警信息包
 * @param  data             My Param doc
 * @param  data_len         My Param doc
 * @return int32_t
 */
int32_t swei_packet_alarm_data(uint8_t *data, uint16_t data_len)
{
    swei_alarmtype_t node;
    common_msg_st gsensor_common_msg;
    // uint16_t msg_len;

    swei_alarm_peek(&node);

    /* 简化处理:两字节告警ID和告警长度和内容,时间戳信息在封装body自行生产 */
    gsensor_common_msg.msg_content[0] = (node.id >> 8) & 0xff;
    gsensor_common_msg.msg_content[1] = node.id & 0xff;

    /* 告警内容长度 */
    gsensor_common_msg.msg_content[2] = 0x00;

    /* 2. 封装消息*/
    return swei_package_protocol_msg(&gsensor_common_msg, NULL, NET_PROTOCOL_ID_WARNING, data);
}

/**
 * @brief 封装状态信息包
 * @param  data             My Param doc
 * @param  data_len         My Param doc
 * @return int32_t 封装数据长度 0 - 无数据待发送
 */
int32_t swei_packet_status_data(uint8_t *data, uint16_t data_len)
{
    uint8_t *ptr = data;
    common_msg_st msg = {0};
    int32_t ret = 0;

    /* 1. 从队列获取状态信息 */
    if (0 != (ret = swei_status_event_peek(&msg))) {
        return ret;
    }
        
    /* 2. 封装消息*/
    ret = swei_package_protocol_msg(&msg, NULL, NET_PROTOCOL_ID_DEVICE_STATUS, ptr);
    if (ret <= 0) {
        log_e("package status data failed! ret = %d\r\n", ret);
        return ret;
    } else {
        ptr += ret;
        ptr -= sizeof(NET_PROTOCOL_HEAD_ST);    // swei_package_protocol_msg内会 +sizeof(NET_PROTOCOL_HEAD_ST);为了达到KLV结构
    }

    return ret;
}

/**
 * @description:
 * @param {common_msg_st} *msg
 * @param {unsigned char} *body_data
 * @param {int32_t} *body_data_len
 * @return {*}
 * @Date: 2024-02-22 15:50:00
 * @modification:
 */
static int32_t swei_package_config_info_body_data(common_msg_st *p_msg, uint8_t *body_data, uint16_t *body_data_len)
{
    unsigned char msg_type = p_msg->msg_type;
    unsigned short data_len = 0;
    platform_config_param_st platform_config_param = swei_config_get(); // 获取配置数据
    uint32_t time = 0;

    body_data[data_len++] = msg_type;
    // 上传常用配置信息
    if (msg_type == 1)
    {
        body_data[data_len++] = platform_config_param.common.shake_sensitivity;
        body_data[data_len++] = platform_config_param.common.ble_distance;
        body_data[data_len++] = platform_config_param.common.ble_insen_unlock;
        body_data[data_len++] = platform_config_param.common.sound_status;
        
        /* 0：音效1 / 1：音效2 / 2 自定义（注：第一字节表示音效，当为2时，第2字节开始为音效文件url）/3:关闭声音 */
        body_data[data_len++] = platform_config_param.common.power_on_sound.status;
        if (SELF_DEFINE == platform_config_param.common.power_on_sound.status) {
            snprintf((char *)&body_data[data_len], sizeof(body_data) - data_len, "%s", platform_config_param.common.power_on_sound.url);
            data_len += strlen(platform_config_param.common.power_on_sound.url) + 1;
        }
        body_data[data_len++] = platform_config_param.common.power_off_sound.status;
        if (SELF_DEFINE == platform_config_param.common.power_off_sound.status) {
            snprintf((char *)&body_data[data_len], sizeof(body_data) - data_len, "%s", platform_config_param.common.power_off_sound.url);
            data_len += strlen(platform_config_param.common.power_off_sound.url) + 1;
        }        
        body_data[data_len++] = platform_config_param.common.find_bike_sound.status;
        if (SELF_DEFINE == platform_config_param.common.find_bike_sound.status) {
            snprintf((char *)&body_data[data_len], sizeof(body_data) - data_len, "%s", platform_config_param.common.find_bike_sound.url);
            data_len += strlen(platform_config_param.common.find_bike_sound.url) + 1;
        }        
        body_data[data_len++] = platform_config_param.common.ride_abnormal_sound.status;
        if (SELF_DEFINE == platform_config_param.common.ride_abnormal_sound.status) {
            snprintf((char *)&body_data[data_len], sizeof(body_data) - data_len, "%s", platform_config_param.common.ride_abnormal_sound.url);
            data_len += strlen(platform_config_param.common.ride_abnormal_sound.url) + 1;
        }           

        body_data[data_len++] = platform_config_param.common.low_power_sound;
        body_data[data_len++] = platform_config_param.common.battery_abnormal_sound;
        body_data[data_len++] = platform_config_param.common.shift_sound;
        body_data[data_len++] = platform_config_param.common.ble_match_sound;
        body_data[data_len++] = platform_config_param.common.charger_link_sound.status;
        if (SELF_DEFINE == platform_config_param.common.charger_link_sound.status) {
            snprintf((char *)&body_data[data_len], sizeof(body_data) - data_len, "%s", platform_config_param.common.charger_link_sound.url);
            data_len += strlen(platform_config_param.common.charger_link_sound.url) + 1;
        }    
        
        body_data[data_len++] = platform_config_param.common.buttery2_link_sound;
        body_data[data_len++] = platform_config_param.common.in_ele_fance_sound;
        body_data[data_len++] = platform_config_param.common.sound_volume;
        // Tbox数据上传间隔
        body_data[data_len++] = 1;
        time = swei_config_rpt_intval_get(CONFIG_GPSINFO_INTERVAL);
        body_data[data_len++] = (time >> 8) & 0xff;
        body_data[data_len++] = time & 0xff;

        body_data[data_len++] = 2;
        time = swei_config_rpt_intval_get(CONFIG_CANINFO_INTERVAL1);
        body_data[data_len++] = (time >> 8) & 0xff;
        body_data[data_len++] = time & 0xff;

        body_data[data_len++] = 3;
        time = swei_config_rpt_intval_get(CONFIG_CANINFO_INTERVAL2);
        body_data[data_len++] = (time >> 8) & 0xff;
        body_data[data_len++] = time & 0xff;

        body_data[data_len++] = 4;
        time = swei_config_rpt_intval_get(CONFIG_HEARTBEAT_INTERVAL);
        body_data[data_len++] = (time >> 8) & 0xff;
        body_data[data_len++] = time & 0xff;
    }
    // 上传Gsensor-manager配置信息
    else if (msg_type == 2)
    {
        data_len += bigending2buf(body_data + data_len, platform_config_param.gsensor_manager.tilt_acc);
        body_data[data_len++] = platform_config_param.gsensor_manager.tilt_time;
        body_data[data_len++] = platform_config_param.gsensor_manager.tilt_gyro;
        body_data[data_len++] = platform_config_param.gsensor_manager.tilt_val;
        data_len += bigending2buf(body_data + data_len, platform_config_param.gsensor_manager.over_acc);
        body_data[data_len++] = platform_config_param.gsensor_manager.over_time;
        body_data[data_len++] = platform_config_param.gsensor_manager.over_gyro;
        body_data[data_len++] = platform_config_param.gsensor_manager.over_val;
        body_data[data_len++] = (platform_config_param.gsensor_manager.unusual_move_check_time >> 8) & 0xff;
        body_data[data_len++] = platform_config_param.gsensor_manager.unusual_move_check_time & 0xff;
        body_data[data_len++] = (platform_config_param.gsensor_manager.tremos_check_time >> 8) & 0xff;
        body_data[data_len++] = platform_config_param.gsensor_manager.tremos_check_time & 0xff;
    }
    // 上传Gsensor-driver配置信息
    else if (msg_type == 3)
    {
        body_data[data_len++] = platform_config_param.gsensor_driver.interrupt_threshold;
        body_data[data_len++] = platform_config_param.gsensor_driver.measure_range;
        body_data[data_len++] = platform_config_param.gsensor_driver.sample_frequecy;
        body_data[data_len++] = platform_config_param.gsensor_driver.reading_count;
        body_data[data_len++] = (platform_config_param.gsensor_driver.thread_interval >> 8) & 0xff;
        body_data[data_len++] = platform_config_param.gsensor_driver.thread_interval & 0xff;
    }

    *body_data_len = data_len;
    return 0;
}

/// @brief  打包需要发送的数据
/// @param  data type which will be packet
/// @param  data buffer for recieve packet data
/// @return >=0 means data packet success, < 0 means data packet failed
int32_t swei_packet_message(data_type_e type, uint8_t *data, uint16_t data_len)
{
    int32_t ret_len = 0;

    if (NULL == data || 0 == data_len)
        return 0;

    switch (type) {
        case TYPE_LOC: /** report gnss, lbs, wifiscan info */
            ret_len = swei_packet_loc_data(data, data_len);
            break;

        case TYPE_ALARM: /** report alarm generated by gsensor, such as shake,tile,tumbling,abnormal move etc */
            ret_len = swei_packet_alarm_data(data, data_len);
            break;

        case TYPE_STATUS: /** report the running status of car, such as errors, bms status and ecu status */
            ret_len = swei_packet_status_data(data, data_len);
            break;

        case TYPE_CONFIG: /** report the device config */
            ret_len = swei_packet_config_data(data, data_len);
            break;

        default:
            break;
    }

    return ret_len;
}

/**
 * @brief 检查GPS数据是否正常
 * @param  gps_info         My Param doc
 * @return true
 * @return false
 */
static bool swei_location_check_gps_info(gps_info_st gps_info)
{
    if ((gps_info.utc_time == 0) ||
        ((gps_info.latitude == 0) && (gps_info.longitude == 0)) ||
        (gps_info.satellite_num <= 1))
    {
        return false;
    }
    return true;
}

/**
 * @brief 度分格式转化
 * @param  ddd - 度格式的经纬度
 * @return float 
 */
float ddd2dmm(float ddd)
{
    float d = (int)ddd;
    float m = (ddd - d) * 60;

    return d * 100 + m;
}

/**
 * @description: 获取gps信息
 * @param {common_msg_st} *msg 返回队列数据
 * @return {*}
 * @Date: 2023-08-10 16:52:23
 * @modification:
 */
int32_t swei_location_scan_gps_info(common_msg_st *msg, uint8_t upload_mode)
{
    struct fix_info info = {0};
    struct sat_info sat;
    uint32_t count;

    gps_info_st gps_info; // gps信息，写入队列的数据
    uint32_t time = 0;
    static uint32_t last_time = 0; // 上一次时间戳

    // log_d("get the lastest location data and push into the cache queue!\r\n");

    get_last_gnss_info(&info);
    get_last_sat_info(&sat, &count);
    if (info.state != FIX_OK)
    {
        // log_e("gps fix failed!\r\n");
        return -EIO;
    }

#ifdef USE_TEST_GPS_INFO // 使用模拟数据进行测试
    gps_info.gps_num = 1;
    time = mktime(&info.utc) + info.utc_ms;
    gps_info.utc_time = time;
    //[lat:2239.625125, lng:11407.531703, speed:0.000000, num:2, utc_time:-1484793416]
    gps_info.latitude = (int32_t)(1139479661);
    gps_info.longitude = (int32_t)(225735593);
    gps_info.altitude = (int32_t)(1014); // 0.1m
    gps_info.speed = (unsigned short)(00);
    gps_info.satellite_num = (int32_t)5;
    gps_info.upload_mode = 0;
    gps_info.status = (int32_t)0; // 航向/状态
#else
    gps_info.gps_num = 1;
    time = mktime(&info.utc) + info.utc_ms;
    gps_info.utc_time = time;
    //[lat:2239.625125, lng:11407.531703, speed:0.000000, num:2, utc_time:-1484793416]
    gps_info.latitude = (int32_t)(ddd2dmm(info.latitude) * 100000);
    gps_info.longitude = (int32_t)(ddd2dmm(info.longitude) * 100000);
    gps_info.altitude = (int32_t)(info.altitude * 10); // 0.1m
    gps_info.speed = (unsigned short)(info.speed * 100);
    gps_info.satellite_num = (int32_t)count;
    gps_info.upload_mode = upload_mode;
    gps_info.status = (int32_t)info.angle; // 航向/状态  
#endif

    // 更新拐点信息，定时上报时不再触发拐点
    if (upload_mode != 0x02)
        check_corner(&info, 1);

#if 0 // #25625 【IoT】 GPS定位信息包(0x0003)域信号强度与log对应点不一致
    // 冒泡获取前3个最大的cn值
    int32_t i = 0;
    int32_t j = 0;
    for (i = 0; i < 3; i++)
    {
        // 从后面往前面冒泡
        for (j = sizeof(sat.sat) / sizeof(sat.sat[0]) - 1; j > i; j--)
        {
            if (sat.sat[j].signal_strength > sat.sat[j - 1].signal_strength)
            {
                int32_t temp = sat.sat[j].signal_strength;
                sat.sat[j].signal_strength = sat.sat[j - 1].signal_strength;
                sat.sat[j - 1].signal_strength = temp;
            }
        }
    }
    gps_info.cn[0] = (char)sat.sat[0].signal_strength;
    gps_info.cn[1] = (char)sat.sat[1].signal_strength;
    gps_info.cn[2] = (char)sat.sat[2].signal_strength;
#else
    gnss_signal_best_get((uint8_t *)gps_info.cn, 3);
#endif

    if (last_time == time)
    {
        log_d("=== same time , last_time[%d] time[%d]", last_time, time);
    }
    last_time = time;

    // 判断gps数据是否有效
    log_i("tbox check gps info,[lat:%d long:%d num:%d[%d][%d][%d][%#x]", gps_info.latitude, gps_info.longitude,
          gps_info.satellite_num, gps_info.cn[0], gps_info.cn[1], gps_info.cn[2], gps_info.upload_mode);
    if (false == swei_location_check_gps_info(gps_info))
    {
        return -EIO;
    }

    // 队列数据
    if (msg)
    {
        msg->msg_type = LOCATION_MODE_GPS;
        memcpy(msg->msg_content, &gps_info, sizeof(gps_info));
        msg->msg_len = sizeof(gps_info);
    }

    return 0;
}

#define MAX_WIFI_SCAN_NUM	(64)
#define MIN_WIFI_SCAN_NUM	(0)
#define MAX_WIFI_SCAN_TIME	(60)
#define MIN_WIFI_SCAN_TIME	(0)


#include "mmgr/include/mmgr_modem.h"
typedef struct NIC_INFO_S{
    char mac[32];
}NIC_INFO;//网卡物理信息

typedef enum 
{
    FW_WIFI_AP_OPEN = 0, 
    FW_WIFI_AP_SHARED = 1, 
    FW_WIFI_AP_WPA_PSK = 2, 
    FW_WIFI_AP_WPA2_PSK = 3, 
    FW_WIFI_AP_WPA_WPA2_PSK = 4, 
    FW_WIFI_AP_AUTH_MAX = 5
}FW_WIFI_AUTH_E;

typedef struct AP_S{
        char mac[18]; //such as 94:65:2d:c0:1b:f8
        int32_t rssi;
        int32_t channel;    
        unsigned char ssid[120]; //UTF-8 编码
        FW_WIFI_AUTH_E crypto; 
}AP_INFO;


 typedef struct DEV_INFO_SCAN_S{
    AP_INFO scan_result[MAX_WIFI_SCAN_NUM];
    int32_t ap_num;
 }DEV_INFO_SCAN;

 #pragma pack(1)
// wifi定位信息
typedef struct
{
    char mac[6];        // mac地址
    char rssi;          // 信号强度
    char wifi_name_len; // wifi名长度
    // ssid
} WIFI_INFO_ST;
#pragma pack()

/**
 * @brief 获取WIFI信息 @TODO:log打印频繁
 * @param  msg              My Param doc
 * @return int32_t
 */
int32_t swei_location_scan_wifi_info(common_msg_st *msg)
{
    uint8_t wifi_totoal_count = 0;
    struct wifi_info * wifi = NULL;

    WIFI_INFO_ST wifi_info; // wifi定位数据
    uint32_t timestamp = swei_get_device_timestamp();

    if((wifi_totoal_count = mmgr_wifi_count_get()) <= 0)
    {
        return -EIO;
    }

    wifi = mmgr_wifi_info_get();
    
    uint8_t wifi_num = (wifi_totoal_count > 3) ? 3 : wifi_totoal_count;

    msg->msg_len = 0;
    memcpy(msg->msg_content + msg->msg_len, &timestamp, sizeof(timestamp)); // 时间戳
    msg->msg_len += sizeof(timestamp);
    msg->msg_content[msg->msg_len] = (char)wifi_num; // wifi个数，最后再修改 msg->msg_content[4]
    msg->msg_len++;

    // 获取信号最强的3个
    int32_t i = 0;
    int32_t num[3] = {wifi_totoal_count, wifi_totoal_count, wifi_totoal_count}; // 从大到小排序
    int32_t max = -128;

    int32_t j = 0;
    for (j = 0; j < 3; j++)
    {
        max = -128;
        for (i = 0; i < wifi_totoal_count; i++)
        {
            if ((num[0] != wifi_totoal_count && i == num[0]) ||
                (num[1] != wifi_totoal_count && i == num[1]) ||
                (num[2] != wifi_totoal_count && i == num[2]))
            {
                continue;
            }
            if (wifi->rssi[i] > max)
            {
                max = wifi->rssi[i];
                num[j] = i;
            }
        }
    }

    for (i = 0; i < wifi_num; i++)
    {
        int32_t idx = num[i];
        memset(&wifi_info, 0, sizeof(wifi_info));
        // 数据转化
        sscanf(wifi->mac[idx], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
               (uint8_t *)&wifi_info.mac[0], (uint8_t *)&wifi_info.mac[1], (uint8_t *)&wifi_info.mac[2],
               (uint8_t *)&wifi_info.mac[3], (uint8_t *)&wifi_info.mac[4], (uint8_t *)&wifi_info.mac[5]);
        wifi_info.rssi = wifi->rssi[idx];
        wifi_info.wifi_name_len = 0; //(WIFI_NAME_MAX_LEN < strlen((char *)info.scan_result[idx].ssid)) ? WIFI_NAME_MAX_LEN : (char)strlen((char *)info.scan_result[idx].ssid);

        // 判断数据是否有效
        if ((wifi_info.mac[0] | wifi_info.mac[1] | wifi_info.mac[2] |
             wifi_info.mac[3] | wifi_info.mac[4] | wifi_info.mac[5]) == 0) // CORRECTED:此处为或运算，仅所有数据都为零才会过滤
        {
            log_e("tbox wifi mac err\r\n");
            return -1;
        }

        if (msg->msg_len + sizeof(wifi_info) + wifi_info.wifi_name_len > MSG_CONTENT_LEN) // 数据过长，跳出循环
        {
            break;
        }

        // 队列数据
        msg->msg_type = LOCATION_MODE_WIFI;
        memcpy(msg->msg_content + msg->msg_len, &wifi_info, sizeof(wifi_info));
        msg->msg_len += sizeof(wifi_info);
        // memcpy(msg->msg_content + msg->msg_len, info.scan_result[idx].ssid, wifi_info.wifi_name_len);
        msg->msg_len += wifi_info.wifi_name_len;
        // CORRECTED
        log_d("=%d=mac %s rssi %d \r\n", idx, wifi->mac[idx], wifi->rssi[idx]);
    }

    msg->msg_content[4] = i; // wifi个数
    if (i == 0)
    {
        log_e("tbox get wifi info fail!");
        return -EIO;
    }

    return 0;
}

#include "modem/qlmodem/task_modem.h"
#include "mmgr/include/mmgr_misc.h"


/**
 * @brief 获取LBS信息
 * @param  msg              My Param doc
 * @return int32_t
 */
int32_t swei_location_scan_lbs_info(common_msg_st *msg)
{
    stations_info_head_st stations_info_head;
    stations_info_st stations_info;         // 2g3g基站定位数据
    stations_info_st_4_5 stations_info_4_5; // 4g5g基站
    uint32_t timestamp = swei_get_device_timestamp();
    struct cell_info srv_cell = {0};
    struct cell_info nbr_cell[5] = {0};
    uint8_t nbr_count = 0;

    // 1. 获取基站信息
    if(0 != modem_get_cell_info(&srv_cell, &nbr_cell, &nbr_count)){
        log_e("get cell info fail!\r\n");
        return -EIO;
    }

    msg->msg_len = 0;
    // 2. 基站信息头数据转化为结构体变量
    stations_info_head.timestamp = timestamp;             // 时间戳
    stations_info_head.lbs_type = LOT_LTE_MODE;        // TODO:info.cg_info[0].status; //  基站类型
    stations_info_head.mnc = srv_cell.mnc;
    stations_info_head.mcc = srv_cell.mcc;
    stations_info_head.lbs_num = 1 + nbr_count > 2 ? 2 : nbr_count;

    // 3. 拷贝基站信息头数据存入消息结构体变量msg
    memcpy(msg->msg_content + msg->msg_len, &stations_info_head, sizeof(stations_info_head));
    msg->msg_len += sizeof(stations_info_head);

    // 4. 主服务基站信息存入消息结构体变量msg
    memset(&stations_info, 0, sizeof(stations_info));
    stations_info.lac = srv_cell.lac;   
    stations_info.cellid = srv_cell.cellid;
    stations_info.csq_rssi = (srv_cell.rssi < 0) ? (0 - srv_cell.rssi) : srv_cell.rssi;
    memcpy(msg->msg_content + msg->msg_len, &stations_info, sizeof(stations_info));
    msg->msg_len += sizeof(stations_info);

    // 5. 选择3个信号强度较好临近基站信息
    int32_t i = 0;
    // for (i = 0; i < lbs_num; i++)
    // {
    //     log_i("--!-- [%d][%d][type %d][%s][%s]", info.cg_info[i].cellid, info.cg_info[i].csq_rssi,
    //           info.cg_info[i].status, info.cg_info[i].mcc, info.cg_info[i].mnc);
    // }
    // 5.1 获取信号最强的3个
    int32_t num[3] = {nbr_count, nbr_count, nbr_count}; // 从大到小排序
    int32_t max = -128;
    int32_t j = 0;
    for (j = 0; j < 3; j++) {
        max = -128;
        for (i = 0; i < nbr_count; i++) {
            if ((num[0] != nbr_count && i == num[0]) ||
                (num[1] != nbr_count && i == num[1]) ||
                (num[2] != nbr_count && i == num[2])) {
                continue;
            }
            if (nbr_cell[i].rssi > max) {
                max = nbr_cell[i].rssi;
                num[j] = i;
            }
        }
    }

    // 5.2 临近基站信息拷贝入msg
    int32_t lbs_num = (nbr_count > 3) ? 3 : nbr_count;
    for (i = 0; i < lbs_num; i++)
    {
        int32_t idx = num[i];

        // 2/3G基站拷贝
        if (stations_info_head.lbs_type < LOT_LTE_MODE)
        {
            if (msg->msg_len + sizeof(stations_info) > MSG_CONTENT_LEN) // 数据过长，跳出循环
            {
                break;
            }
            memset(&stations_info, 0, sizeof(stations_info));

            stations_info.lac    = nbr_cell[idx].lac;   
            stations_info.cellid = nbr_cell[idx].cellid;
            stations_info.csq_rssi = (nbr_cell[idx].rssi < 0) ? (0 - nbr_cell[idx].rssi) : nbr_cell[idx].rssi;

            // 队列数据转入msg结构体变量
            memcpy(msg->msg_content + msg->msg_len, &stations_info, sizeof(stations_info));
            msg->msg_len += sizeof(stations_info);
            log_d("=%d= rssi[%d] cellid[%d][%d]\r\n", idx, stations_info.csq_rssi,
                                            stations_info.cellid, 
                                            stations_info.cellid);
        }
        else
        {   /* 3/4/5G基站 */
            if (msg->msg_len + sizeof(stations_info_4_5) > MSG_CONTENT_LEN) // 数据过长，跳出循环
            {
                break;
            }
            memset(&stations_info_4_5, 0, sizeof(stations_info_4_5));
            // lac底层无法获取到
            stations_info_4_5.cellid = (uint64_t)nbr_cell[idx].cellid;
            // 信号值应该为负数，因为订协议的人执意要用绝对值，所以加了这个转化
            stations_info_4_5.csq_rssi = (nbr_cell[idx].rssi < 0) ? (0 - nbr_cell[idx].rssi) : nbr_cell[idx].rssi;

            // 队列数据
            msg->msg_type = LOCATION_MODE_STATIONS;
            memcpy(msg->msg_content + msg->msg_len, &stations_info_4_5, sizeof(stations_info_4_5));
            msg->msg_len += sizeof(stations_info_4_5);
            log_d("=%d= rssi[%d] cellid[%d][%lld]\r\n", idx, stations_info_4_5.csq_rssi,
                    stations_info_4_5.cellid, stations_info_4_5.cellid);
        }
    }

    msg->msg_type = LOCATION_MODE_STATIONS;

    return 0;
}




